Claude Code 攻略 1.2 - LLM 如何"理解"代码

2025-12-22 | 95分钟 | yrobot | LLM,大语言模型,Transformer,注意力机制,模式匹配,能力边界,工具增强

LLM 究竟如何工作?

在使用 Claude Code 的过程中,我一直有个疑惑:AI 是如何"理解"代码的?

表面上看,它能读懂代码逻辑、发现 bug、提出重构建议,这些都像是真正的"理解"。但仔细想想,LLM 的本质不就是"预测下一个词"吗?如果只是统计概率,为什么能解决复杂的编程问题?

这个问题一直困扰着我,直到我开始深入学习 LLM 的工作原理。我发现,理解 LLM 的能力边界,对于用好 Claude Code 至关重要。因为只有知道它"能做什么、不能做什么、为什么能做",才能合理地使用工具,避免不切实际的期待。

这篇文章,我会从 LLM 的本质讲起,解答以下问题:

  • LLM 究竟是什么?和其他大模型有什么区别?
  • 如果 LLM 只是"预测下一个词",它怎么能解决复杂问题?
  • 为什么代码任务特别适合 LLM?
  • Transformer 的注意力机制到底是什么?
  • 为什么需要 Claude Code 这样的工具,而不只是 ChatGPT?

LLM 是什么

本质定义

LLM = Large Language Model(大语言模型)

它的本质是:基于大量文本数据训练的神经网络模型,专注于理解和生成自然语言

更通俗的理解:

  • 你给它一段文字(输入)
  • 它预测接下来最可能出现的文字(输出)
  • 通过这种方式完成对话、写作、翻译、代码生成等任务

与其他大模型的区别

在研究 LLM 的过程中,我发现大模型其实有很多种类,按处理的数据类型可以分为:

类型 处理对象 典型代表 核心能力
LLM 文本 GPT-4、Claude、Gemini 逻辑推理、文字生成、代码理解
VLM 图像+文本 GPT-4V、Claude 3.5 图片理解、图文对话
Diffusion Model 图像生成 Stable Diffusion、Midjourney 文生图、图像编辑
Multimodal Model 多种类型 GPT-4o、Gemini Ultra 跨模态理解与生成

核心差异

  • 训练数据不同:LLM 主要使用文本(网页、书籍、代码),图像模型使用图像+描述
  • 应用场景不同:LLM 强在逻辑推理和文字生成,图像模型强在视觉创作

Claude Code 是 LLM 吗?

这是一个容易混淆的概念。准确答案:Claude Code 不是 LLM,而是基于 LLM 构建的应用工具

理解这个层次关系很重要:

Claude 3.5 Sonnet(LLM 模型)
    ↓ 理解和生成文本
Claude API(API 服务)
    ↓ 提供模型调用接口
Claude Code(应用工具)
    ↓ LLM + 工具系统(文件操作、代码执行、网络访问等)

为什么这个区别重要?

因为它解释了:

  • 为什么 Claude Code 能操作文件:LLM 本身不能,但工具系统可以
  • 为什么 Claude Code 能执行代码:LLM 本身不能,但沙箱环境可以
  • 为什么 Claude Code 有 Plan Mode:这是应用层的设计,不是模型能力

LLM 如何"理解":模式匹配 vs 真正理解

一开始的困惑

如果 LLM 只是"预测下一个词",为什么看起来像"理解"了?

这是我最困惑的点。比如:

  • 问它"这段代码有什么问题",它能准确指出 bug
  • 问它"如何重构这个函数",它能给出合理的建议
  • 问它"解释这个算法的原理",它能讲得很清楚

这些都像是"理解",但如果只是统计模型,为什么能做到?

关键洞察:模式识别 ≠ 真正理解

答案是:LLM 并不真正"理解",它是在做极其复杂的模式匹配

用一个对比来说明:

人类理解 = 概念 + 因果关系 + 抽象推理
LLM "理解" = 海量模式 + 统计关联 + 上下文推理

具体过程

训练阶段:见过海量的"问题→答案"模式

见过 10000+ 次:"天气怎么样""今天是晴天/雨天/..."
见过 50000+ 次:"这段代码有 bug" → 分析 + 解决方案
见过 100000+ 次:代码上下文 → 合理的代码补全

推理阶段:通过注意力机制组合模式

你的输入:"我在杭州,明天天气怎么样"

LLM 内部处理:
- "我在杭州" → 地点信息(高关注度)
- "明天" → 时间信息(高关注度)
- "天气" → 查询类型(高关注度)
- 组合这些模式 → 生成符合模式的输出

但这不是真正的理解

举个例子就能看出差异:

问:如果一个人从高楼跳下,会发生什么?
LLM:会受重力影响下落,可能受伤或死亡

问:如果一个人从高楼"往上"跳,会发生什么?
LLM:仍然会受重力影响下落(匹配到"从高楼跳"的模式)

LLM 不理解

  • "往上跳"的物理含义(人无法违反重力)
  • 这是一个不合理的问题

它只是匹配

  • "高楼 + 跳" → 坠落场景

关于训练数据的局限

这也解释了为什么 LLM 对训练数据之后的内容"不知道":

如果你问:"2024 年最新的网络梗是什么?"

LLM 可能:
- 诚实回答"我不知道"(训练数据截止于 20241 月)
- 编造答案(幻觉)

但如果你提供上下文:
"最近流行一个梗'xx',意思是..."
LLM:能理解!因为有上下文

本质:LLM 的"理解"依赖于:

  • 训练数据中的模式
  • 当前对话的上下文
  • 两者的组合

为什么"预测下一个词"能解决复杂问题

关键机制:思维链(Chain-of-Thought)

虽然 LLM 不"理解",但它能"模仿推理":

简单任务:直接预测
你:"1+1=?"
LLM:"2"

复杂任务:分步推理
你:"一个项目有 10 个文件,每个文件平均 100 行,重构需要多久?"

LLM 内部推理链:
"这需要分步思考""第一步:总代码量 = 10 * 100 = 1000 行""第二步:重构速度取决于复杂度...""第三步:综合考虑..." →
最终答案

为什么有效

因为训练数据中包含大量"推理过程":

  • 教科书的分步解题
  • 代码注释的逻辑说明
  • 博客文章的思路展开

**LLM 学会了"模仿推理"**:

  • 不是真正的逻辑推理
  • 而是学习到了"什么样的推理过程是合理的"模式

代码生成的例子

代码上下文:
def calculate_total(items):
    # 计算所有商品的总价
    total = 0
    for item in items:
        total += ___

问题:下划线处应该填什么?

LLM 的处理过程

  1. 识别模式:"total +=" → 累加操作
  2. 分析上下文:"items" → 商品列表,"item" → 当前商品
  3. 提取关键信息:"总价" + "商品" → 需要价格属性
  4. 组合模式:item.price

为什么代码任务特别适合 LLM

在学习过程中,我发现了一个有趣的现象:LLM 在代码任务上的表现,往往比自然语言任务更稳定。这是为什么?

1. 代码的规范性强

自然语言:"今天天气真好"
可能的延续:
- "我们去郊游吧"(建议)
- "是啊,很适合运动"(认同)
- "但我心情不好"(转折)
- ... 无限可能

代码:"function add(a, b) {"
可能的延续:
- "return a + b;" (高概率,符合函数名)
- "return a - b;" (低概率,不符合函数名)
- "console.log('hello');" (极低概率,不符合逻辑)

关键差异

维度 自然语言 代码
语法规则 灵活、模糊 严格、确定
验证方式 主观理解 可执行、可测试
正确性 "合理即可" "正确或错误"

2. "合理" vs "正确"

自然语言任务:
问:"今天心情不好,怎么办?"
回答 A"去运动一下"
回答 B"找朋友聊聊"
回答 C"听音乐放松"
→ 都合理,没有绝对的"对错"

编程任务:
问:"写一个排序函数"
回答 A:正确的快速排序
回答 B:有 bug 的快速排序
回答 C:正确的冒泡排序
→ 有明确的"对错"

3. 代码的可组合性

代码比自然语言更容易组合和复用:

自然语言:
句子 A:"我喜欢吃苹果"
句子 B:"苹果很健康"
组合:"我喜欢吃苹果,苹果很健康"
→ 需要调整语序、添加连接词

代码:
函数 A:function readFile(path) { ... }
函数 B:function parseJSON(text) { ... }
组合:const data = parseJSON(readFile(path))
→ 直接组合,无需修改

对 LLM 的意义

  1. 模式复用更容易

    见过:读取文件 → 解析 JSON
    见过:读取文件 → 解析 CSV
    推理:读取文件 → 解析 YAML(新组合)
  2. 上下文依赖更清晰

    // 函数签名明确输入输出
    function add(a: number, b: number): number
    // LLM 知道:输入类型、输出类型、行为预期
  3. 错误反馈更精确

    自然语言:"这句话不太对"(模糊)
    代码:"TypeError: expected string, got number"(精确)

Transformer:LLM 的"超能力"来源

用类比理解:阅读理解考试

想象你在做一道阅读理解题:

传统方式(RNN/LSTM)

文章:"小明早上起床,刷牙洗脸,然后去学校上课。"
问题:"小明去哪里了?"

传统模型(从左到右逐字处理):
"小明" → 记住
"早上" → 更新记忆
"起床" → 更新记忆
...
"学校" → 更新记忆(前面的信息已经模糊了)

问题:像流水账,前面的容易忘

Transformer 方式(注意力机制)

文章:"小明早上起床,刷牙洗脸,然后去学校上课。"
问题:"小明去哪里了?"

Transformer(全局注意力):
看到"去"这个词时,同时看整个句子,判断相关性:
- "小明" → 关联度:90%(主语,重要!)
- "早上" → 关联度:10%(时间,不重要)
- "起床" → 关联度:10%(动作,不重要)
- "学校" → 关联度:95%(地点,核心答案!)

综合分析:
"去" + "学校" 关联强 → 地点是学校
"小明" + "去" 关联强 → 主语是小明

注意力机制的本质

注意力的本质:为每个词计算它与其他所有词的"相关性"

句子:"The cat sat on the mat."

当处理 "sat" 这个词时:

传统模型:
The → cat → sat
→ 只记得前面的 "The cat"

Transformer:
sat 与所有词的注意力分数:
- The: 0.1(冠词,不重要)
- cat: 0.9(主语,重要!)
- sat: 1.0(当前词)
- on: 0.3(介词,有点重要)
- the: 0.1(冠词,不重要)
- mat: 0.6(地点,重要)

综合理解:
"cat" 执行了 "sat" 的动作
动作发生在 "mat"

注意力权重的可视化

句子:"我喜欢吃北京烤鸭"

处理"烤鸭"时的注意力权重:

我      10%  (主语,略相关)
喜欢    30%  (动词,比较相关)80%  (动作,很相关!)
北京    95%  (修饰词,极相关!)
烤鸭    100% (当前词)

结论:
- "烤鸭"主要关注"北京"(地名修饰)
- "烤鸭"关注"吃"(动作对象)
- 理解为:"吃 + 北京的 + 烤鸭"

为什么这个机制如此强大

1. 并行处理

传统 RNN:
word1 → word2 → word3 → word4
→ 必须顺序处理,慢

Transformer:
word1 ────┐
word2 ────┤→ 同时计算所有注意力 → 并行处理
word3 ────┤
word4 ────┘
→ 所有词同时处理,快!

2. 长距离依赖

句子:"我昨天在北京吃了一顿很美味的烤鸭。"
问题:"在哪里吃的?"

传统模型:
从"我""烤鸭"要处理 10+ 个词
中间信息容易丢失

Transformer:
"吃" 可以直接"注意""北京"
不管距离多远,注意力权重直接计算

3. 多头注意力(Multi-Head Attention)

类比:用不同的视角同时看文章

文章:"小明在学校学习编程。"

Head 1(关注"谁"):
小明    主语
学校    地点(略相关)

Head 2(关注"在哪"):
学校    地点
学习    动作(略相关)

Head 3(关注"做什么"):
学习    动作
编程    对象

综合三个视角 → 完整理解:
"小明(谁)在学校(哪)学习编程(做什么)"

代码理解的例子

代码:
const user = await fetchUser(userId);
const orders = await fetchOrders(user.id);
const total = calculateTotal(orders);
return { user, orders, total };

Transformer 的优势:
1. 同时"看到"所有行
2. 理解 userId → user.id → orders 的数据流
3. 理解 orders → calculateTotal → total 的转换
4. 理解最终返回的结构

这就是为什么 LLM 能:
- 理解代码逻辑
- 发现潜在 bug
- 建议重构方案

LLM 的能力边界

理解了 LLM 的工作原理后,我们也能更清楚地认识它的局限:

维度 LLM 能做到 LLM 做不到
理解 模式匹配、上下文推理 真正的语义理解、因果推理
记忆 基于上下文"记住" 长期记忆、跨会话记忆
推理 模仿推理过程 严格的逻辑证明
创造 组合已知模式 真正的创新
验证 生成看似合理的内容 保证事实正确

典型的能力边界

能做好的

  • 样板代码生成
  • API 使用示例
  • 代码解释与重构
  • 简单 Bug 修复

做不好的

  • 复杂系统架构设计
  • 性能优化(需要数据驱动)
  • 安全审计(需要严格验证)
  • 超长代码库的全局理解

为什么需要工具增强

基于上面的分析,我们能清楚地看到:LLM 单独使用有很大局限

LLM 的三大局限

  1. 上下文窗口有限:无法加载整个项目
  2. 无法执行代码:无法验证生成的代码是否正确
  3. 无法访问外部资源:无法读取文件、调用 API

工具系统的三个核心价值

价值 1:自动化上下文获取

没有工具:
用户:"帮我修复这个 bug"
LLM:"请提供代码"
用户:复制粘贴代码
LLM:"请提供错误信息"
用户:复制粘贴错误
→ 效率低、容易遗漏

有工具(Claude Code):
用户:"帮我修复这个 bug"
Claude Code:
1. Read(错误文件) → 自动获取代码
2. Bash(npm test) → 自动获取错误信息
3. Grep(相关函数) → 自动获取依赖关系
4. 分析 → 修复 → 验证
→ 效率高、上下文完整

价值 2:执行验证与迭代

传统方式(ChatGPT):
AI 生成代码 → 用户复制 → 用户粘贴 → 用户运行 → 有错误 → 用户再问 AI
→ 每一步都可能出错

Claude CodeAI 生成代码 → 自动写入文件 → 自动运行测试 → 有错误 → 自动读取错误 → AI 自动修正
→ 减少人工环节,提高稳定性

这就是"执行-验证-调整"循环:

计划实施 → 执行代码 → 检查结果 → 发现问题 → 调整方案 → 再次执行
          ↑                                              ↓
          └──────────────────────────────────────────────┘

价值 3:扩展能力边界

LLM 本身不能做的事,工具可以做

任务 LLM 能力 工具能力 组合效果
读取文件 ✅ Read LLM 分析 + 工具读取
执行代码 ✅ Bash LLM 生成 + 工具执行
搜索代码库 ✅ Grep LLM 理解 + 工具搜索
访问网络 ✅ WebFetch LLM 提取 + 工具获取
调用 API ✅ MCP LLM 规划 + 工具调用

Claude Code 的本质

Claude Code = LLM(大脑)+ 工具系统(手脚)

大脑:理解需求、制定计划、分析问题
手脚:执行操作、获取信息、验证结果

为什么理解 LLM 很重要

通过这篇文章的学习,我对 LLM 有了更清晰的认知:

LLM 的本质:

  • 不是"真正理解",而是"复杂的模式匹配"
  • 基于 Transformer 的注意力机制
  • 能力来自于训练数据和上下文

为什么代码任务适合 LLM:

  • 代码规范性强,适合模式匹配
  • 可组合性好,容易复用
  • 可验证性强,有明确的对错

为什么需要工具增强:

  • LLM 有能力边界(无法执行、无法访问外部)
  • 工具系统补足了 LLM 的短板
  • 组合产生了 1+1>2 的效果

对使用 Claude Code 的启示:

  1. 提供充分上下文:LLM 的输出质量取决于输入
  2. 善用工具能力:让 Claude Code 自动获取信息、执行验证
  3. 理解能力边界:不要期待 LLM 做它做不到的事
  4. 建立迭代思维:执行-验证-调整,而不是一次性完成

下一篇文章,我会深入探讨 Prompt Engineering 的核心技巧,教你如何更有效地与 AI 对话。